import flask, flask.views
from flask import request, flash, render_template, redirect, url_for, session
app = flask.Flask(__name__)
app.debug = True
app.secret_key = "Clavea"
app.config.from_object("config")
app.default_user = "admin"
app.default_password = "admin"
from models.usuario import usuario, Usuario
from models.rol import rol, Rol
from models.proyecto import proyecto, Proyecto
from sqlalchemy import select
from sqlalchemy.orm import mapper
from usuarioView import crearUsuario, abmUsuario, modificarUsuario, eliminarUsuario, consultarUsuario
from itemView import verFamiliaItem, verRelacionesItem, verRelacionesProyecto, cargarAtributosPorSC, eliminarRelacionPorSC, modificarRelacionPorSC, modificarItemPorSC, itemsEnSC, adjuntar, crearItem, cargaTipoItem, restaurarItem, cargarAtributos, verRelacionesFase, modificarItemPorSC, itemsEnSC, abmItem,revivirItem, modificarItem, eliminarItem, consultarItem, modificarRelacion, aprobarItem, eliminarRelacion
from tipoItemView import crearTipoItem, abmTipoItem, modificarTipoItem, eliminarTipoItem, eliminarAtributoTipoAsignado, consultarTipoItem, eliminarAtributoTipo, agregarAtributoTipo, modificarAtributoTipo, agregarAtributoTipoAsignado, importarTipoItem
from lineaBaseView import crearLineaBase, abmLineaBase, abrirLineaBase,consultarLineaBase,aprobarLineaBase,modificarLineaBase, agregarItemLb, eliminarItemLb
from rolView import crearRol, abmRol, modificarRol, eliminarRol, consultarRol
from proyectoView import crearProyecto, abmProyecto, modificarProyecto, eliminarProyecto, consultarProyecto, calcularCosto, calcularComplejidad
from comiteView import amComite, agregarIntegrante, modificarIntegrante
from consultasView import consultas, consultarRolesDelProyecto, consultarUsuariosDelProyecto, consultarRolesPorUsuario, consultarUsuariosPorRol, consultarPermisosPorRol
from adRolPorUsuarioView import adRolPorUsuario, agregarRolUsuario, desasignarRolDeUsuario, agregarUsuarioProyecto
from fasesView import gestionarFases, consultarFase, modificarFase, inicializarFase, abrirFase, cerrarFase
from gestionarProyectoView import inicializarProyecto, finalizarProyecto
from otrasConsultasView import otrasConsultas, consultarFasesDelProyecto, consultarTIdelProyecto, consultarLBporFase, consultarTIporFase
from solicitudCambioView import generarSolicitud, gestionarSolicitud, antesGenerarSolicitud, listarSolicitudes, consultarDetalleSolicitud, votarSolicitud, generarInforme
from reportesView import gestionarReportes, reporteItemsPorFase, reporteSolicitudes, reporteHistorial
from flask_weasyprint import HTML, render_pdf
import hashlib
import datetime

# codigos para letras con acentos
#  agregar el prefijo 'u'
# \u00e1 -> a acento
# \u00e9 -> e acento
# \u00ed -> i acento
# \u00f3 -> o acento
# \u00fa -> u acento
# \u00c1 -> A acento
# \u00c9 -> E acento
# \u00cd -> I acento
# \u00d3 -> O acento
# \u00da -> U acento
# \u00f1 -> n enhe
# \u00d1 -> N enhe

from models.proyectoManager import ProyectoManager
from models.faseManager import FaseManager
from models.rolManager import RolManager
from models.usuarioManager import UsuarioManager
from models.permisoManager import PermisoManager
from models.itemManager import ItemManager
rolMgr= RolManager()
usuarioMgr= UsuarioManager()
permisoMgr= PermisoManager()
proyectoMgr= ProyectoManager()
faseMgr= FaseManager()
itemMgr= ItemManager()

# con = engine.connect()

#app.config.from_object(__name__)
#app.config.from_envvar('EPM_SETTINGS', silent=True)
#app.config.from_pyfile('/home/verena/git/is2-epm/config.cfg')

# app.add_url_rule(rule="/elegirItem", view_func=elegirItem, methods=["GET", "POST"])
app.add_url_rule(rule="/gestionarReportes", view_func=gestionarReportes, methods=["GET", "POST"])
app.add_url_rule(rule="/reporteItemsPorFase", view_func=reporteItemsPorFase, methods=["GET", "POST"])
app.add_url_rule(rule="/reporteSolicitudes", view_func=reporteSolicitudes, methods=["GET", "POST"])
app.add_url_rule(rule="/reporteHistorial", view_func=reporteHistorial, methods=["GET", "POST"])

app.add_url_rule(rule="/generarSolicitud", view_func=generarSolicitud, methods=["GET", "POST"])
app.add_url_rule(rule="/gestionarSolicitud", view_func=gestionarSolicitud, methods=["GET", "POST"])
app.add_url_rule(rule="/listarSolicitudes", view_func=listarSolicitudes, methods=["GET", "POST"])
app.add_url_rule(rule="/consultarDetalleSolicitud", view_func=consultarDetalleSolicitud, methods=["GET", "POST"])
app.add_url_rule(rule="/votarSolicitud", view_func=votarSolicitud, methods=["GET", "POST"])
app.add_url_rule(rule="/generarInforme", view_func=generarInforme, methods=["GET", "POST"])
app.add_url_rule(rule="/antesGenerarSolicitud", view_func=antesGenerarSolicitud, methods=["GET", "POST"])


app.add_url_rule(rule="/otrasConsultas", view_func=otrasConsultas, methods=["GET", "POST"])
app.add_url_rule(rule="/consultarFasesDelProyecto", view_func=consultarFasesDelProyecto, methods=["GET", "POST"])
app.add_url_rule(rule="/consultarTIdelProyecto", view_func=consultarTIdelProyecto, methods=["GET", "POST"])
app.add_url_rule(rule="/consultarLBporFase", view_func=consultarLBporFase, methods=["GET", "POST"])
app.add_url_rule(rule="/consultarTIporFase", view_func=consultarTIporFase, methods=["GET", "POST"])

app.add_url_rule(rule="/crearItem", view_func=crearItem, methods=["GET", "POST"])
app.add_url_rule(rule="/modificarItem", view_func=modificarItem, methods=["GET", "POST"])
app.add_url_rule(rule="/eliminarItem", view_func=eliminarItem, methods=["GET", "POST"])
app.add_url_rule(rule="/aprobarItem", view_func=aprobarItem, methods=["GET", "POST"])
app.add_url_rule(rule="/consultarItem", view_func=consultarItem, methods=["GET", "POST"])
app.add_url_rule(rule="/abmItem", view_func=abmItem, methods=["GET", "POST"])
app.add_url_rule(rule="/modificarRelacion", view_func=modificarRelacion, methods=["GET", "POST"])
app.add_url_rule(rule="/eliminarRelacion", view_func=eliminarRelacion, methods=["GET", "POST"])
app.add_url_rule(rule="/restaurarItem", view_func=restaurarItem, methods=["GET", "POST"])
app.add_url_rule(rule="/cargarAtributos", view_func=cargarAtributos, methods=["GET", "POST"])
app.add_url_rule(rule="/verRelacionesFase", view_func=verRelacionesFase, methods=["GET", "POST"])
app.add_url_rule(rule="/revivirItem", view_func=revivirItem, methods=["GET", "POST"])
app.add_url_rule(rule="/cargaTipoItem", view_func=cargaTipoItem, methods=["GET", "POST"])
app.add_url_rule(rule="/adjuntar", view_func=adjuntar, methods=["GET", "POST"])
app.add_url_rule(rule="/modificarItemPorSC", view_func=modificarItemPorSC, methods=["GET", "POST"])
app.add_url_rule(rule="/itemsEnSC", view_func=itemsEnSC, methods=["GET", "POST"])
app.add_url_rule(rule="/cargarAtributosPorSC", view_func=cargarAtributosPorSC, methods=["GET", "POST"])
app.add_url_rule(rule="/eliminarRelacionPorSC", view_func=eliminarRelacionPorSC, methods=["GET", "POST"])
app.add_url_rule(rule="/modificarRelacionPorSC", view_func=modificarRelacionPorSC, methods=["GET", "POST"])
app.add_url_rule(rule="/verRelacionesProyecto", view_func=verRelacionesProyecto, methods=["GET", "POST"])
app.add_url_rule(rule="/verRelacionesItem", view_func=verRelacionesItem, methods=["GET", "POST"])
app.add_url_rule(rule="/verFamiliaItem", view_func=verFamiliaItem, methods=["GET", "POST"])



app.add_url_rule(rule="/crearTipoItem", view_func=crearTipoItem, methods=["GET", "POST"])
app.add_url_rule(rule="/modificarTipoItem", view_func=modificarTipoItem, methods=["GET", "POST"])
app.add_url_rule(rule="/eliminarTipoItem", view_func=eliminarTipoItem, methods=["GET", "POST"])
app.add_url_rule(rule="/consultarTipoItem", view_func=consultarTipoItem, methods=["GET", "POST"])
app.add_url_rule(rule="/abmTipoItem", view_func=abmTipoItem, methods=["GET", "POST"])
app.add_url_rule(rule="/importarTipoItem", view_func=importarTipoItem, methods=["GET", "POST"])

app.add_url_rule(rule="/crearLineaBase", view_func=crearLineaBase, methods=["GET", "POST"])
app.add_url_rule(rule="/abrirLineaBase", view_func=abrirLineaBase, methods=["GET", "POST"])
app.add_url_rule(rule="/consultarLineaBase", view_func=consultarLineaBase, methods=["GET", "POST"])
app.add_url_rule(rule="/aprobarLineaBase", view_func=aprobarLineaBase, methods=["GET", "POST"])
app.add_url_rule(rule="/modificarLineaBase", view_func=modificarLineaBase, methods=["GET", "POST"])
app.add_url_rule(rule="/abmLineaBase", view_func=abmLineaBase, methods=["GET", "POST"])
app.add_url_rule(rule="/agregarItemLb", view_func=agregarItemLb, methods=["GET", "POST"])
app.add_url_rule(rule="/eliminarItemLb", view_func=eliminarItemLb, methods=["GET", "POST"])

app.add_url_rule(rule="/consultarFase", view_func=consultarFase, methods=["GET", "POST"])
app.add_url_rule(rule="/abrirFase", view_func=abrirFase, methods=["GET", "POST"])
app.add_url_rule(rule="/cerrarFase", view_func=cerrarFase, methods=["GET", "POST"])
app.add_url_rule(rule="/inicializarFase", view_func=inicializarFase, methods=["GET", "POST"])
app.add_url_rule(rule="/modificarFase", view_func=modificarFase, methods=["GET", "POST"])
app.add_url_rule(rule="/gestionarFases", view_func=gestionarFases, methods=["GET", "POST"])

app.add_url_rule(rule="/inicializarProyecto", view_func=inicializarProyecto, methods=["GET", "POST"])
app.add_url_rule(rule="/finalizarProyecto", view_func=finalizarProyecto, methods=["GET", "POST"])

app.add_url_rule(rule="/crearUsuario", view_func=crearUsuario, methods=["GET", "POST"])
app.add_url_rule(rule="/modificarUsuario", view_func=modificarUsuario, methods=["GET", "POST"])
app.add_url_rule(rule="/eliminarUsuario", view_func=eliminarUsuario, methods=["GET", "POST"])
app.add_url_rule(rule="/consultarUsuario", view_func=consultarUsuario, methods=["GET", "POST"])
app.add_url_rule(rule="/abmUsuario", view_func=abmUsuario, methods=["GET", "POST"])

app.add_url_rule(rule="/crearRol", view_func=crearRol, methods=["GET", "POST"])
app.add_url_rule(rule="/modificarRol", view_func=modificarRol, methods=["GET", "POST"])
app.add_url_rule(rule="/eliminarRol", view_func=eliminarRol, methods=["GET", "POST"])
app.add_url_rule(rule="/consultarRol", view_func=consultarRol, methods=["GET", "POST"])
app.add_url_rule(rule="/abmRol", view_func=abmRol, methods=["GET", "POST"])

app.add_url_rule(rule="/crearProyecto", view_func=crearProyecto, methods=["GET", "POST"])
app.add_url_rule(rule="/modificarProyecto", view_func=modificarProyecto, methods=["GET", "POST"])
app.add_url_rule(rule="/eliminarProyecto", view_func=eliminarProyecto, methods=["GET", "POST"])
app.add_url_rule(rule="/consultarProyecto", view_func=consultarProyecto, methods=["GET", "POST"])
app.add_url_rule(rule="/abmProyecto", view_func=abmProyecto, methods=["GET", "POST"])
app.add_url_rule(rule="/calcularComplejidad", view_func=calcularComplejidad, methods=["GET", "POST"])
app.add_url_rule(rule="/calcularCosto", view_func=calcularCosto, methods=["GET", "POST"])

app.add_url_rule(rule="/amComite", view_func=amComite, methods=["GET", "POST"])
app.add_url_rule(rule="/agregarIntegrante", view_func=agregarIntegrante, methods=["GET", "POST"])
app.add_url_rule(rule="/modificarIntegrante", view_func=modificarIntegrante, methods=["GET", "POST"])

app.add_url_rule(rule="/modificarAtributoTipo", view_func=modificarAtributoTipo, methods=["GET", "POST"])
app.add_url_rule(rule="/agregarAtributoTipo", view_func=agregarAtributoTipo, methods=["GET", "POST"])
app.add_url_rule(rule="/eliminarAtributoTipo", view_func=eliminarAtributoTipo, methods=["GET", "POST"])
app.add_url_rule(rule="/eliminarAtributoTipoAsignado", view_func=eliminarAtributoTipoAsignado, methods=["GET", "POST"])
app.add_url_rule(rule="/agregarAtributoTipoAsignado", view_func=agregarAtributoTipoAsignado, methods=["GET", "POST"])

app.add_url_rule(rule="/consultas", view_func=consultas, methods=["GET", "POST"])
app.add_url_rule(rule="/consultarRolesDelProyecto", view_func=consultarRolesDelProyecto, methods=["GET", "POST"])
app.add_url_rule(rule="/consultarUsuariosDelProyecto", view_func=consultarUsuariosDelProyecto, methods=["GET", "POST"])
app.add_url_rule(rule="/consultarRolesPorUsuario", view_func=consultarRolesPorUsuario, methods=["GET", "POST"])
app.add_url_rule(rule="/consultarUsuariosPorRol", view_func=consultarUsuariosPorRol, methods=["GET", "POST"])
app.add_url_rule(rule="/consultarPermisosPorRol", view_func=consultarPermisosPorRol, methods=["GET", "POST"])

app.add_url_rule(rule="/adRolPorUsuario", view_func=adRolPorUsuario, methods=["GET", "POST"])
app.add_url_rule(rule="/agregarRolUsuario", view_func=agregarRolUsuario, methods=["GET", "POST"])
app.add_url_rule(rule="/desasignarRolDeUsuario", view_func=desasignarRolDeUsuario, methods=["GET", "POST"])
app.add_url_rule(rule="/agregarUsuarioProyecto", view_func=agregarUsuarioProyecto, methods=["GET", "POST"])


@app.route('/reporteItems/<name>/')
def hello_html(name):
    return render_template('hello.html', name=name)


@app.route('/reporte1.pdf')
def reporte1_pdf():
    # Make a PDF straight from HTML in a string.
    idproyecto = session['idproyecto']
    proyecto = proyectoMgr.getProyecto(idproyecto)
    fases = faseMgr.getFasesPorProyecto(idproyecto)
    fecha = datetime.date.today()
    html = render_template('reporteItemsPorFase.html', idproyecto=idproyecto, proyecto=proyecto, fases=fases, fecha=fecha, bandera='0')
    return render_pdf(HTML(string=html))

@app.route('/reporte2.pdf')
def reporte2_pdf():
    # Make a PDF straight from HTML in a string.
    idproyecto = session['idproyecto']
    proyecto = proyectoMgr.getProyecto(idproyecto)
    solicitudes = proyectoMgr.getSolicitudesDelProyecto(idproyecto)
    fecha = datetime.date.today()
    html = render_template('reporteSolicitudes.html', idproyecto=idproyecto, proyecto=proyecto, solicitudes=solicitudes, fecha=fecha, bandera='0')
    return render_pdf(HTML(string=html))

@app.route('/reporte3.pdf')
def reporte3_pdf():
    # Make a PDF straight from HTML in a string.
    idproyecto = session['idproyecto']
    proyecto = proyectoMgr.getProyecto(idproyecto)
    iditem = request.args.getlist('iditem')[0]
    print "entra a reporte3"
    proyecto = proyectoMgr.getProyecto(idproyecto)
    item = itemMgr.getItem(iditem)
    items = itemMgr.getItemsDelProyecto(idproyecto)
    fecha = datetime.date.today()
    html = render_template('reporteHistorial.html', idproyecto=idproyecto, proyecto=proyecto, item=item, fecha=fecha, bandera='0')
    return render_pdf(HTML(string=html))

@app.errorhandler(404)
def page_not_found(error):
    return render_template("index.html"), 404

"""Clase que contiene los metodos relacionados con la gestion de la interfaz grafica de usuario"""

@app.route("/configurarProyecto", methods=["GET", "POST"])
def configurarProyecto():
    """Metodo encargado de consultar los datos de un proyecto"""
    if request.method == "GET":
        action = "configurarProyecto"
        if request.args.getlist('action'):
            action = request.args.getlist('action')[0]
        proyectos = proyectoMgr.getProyectos()
        proyecto = None  
        if session['idproyecto']:
            idproyecto = session['idproyecto']
            proyecto = proyectoMgr.getProyecto(idproyecto)
        return render_template("configProyecto.html", action = action, proyecto= proyecto, proyectos = proyectos)
    if request.method == "POST":  
        action = request.form['action']
        proyectos = proyectoMgr.getProyectos()
        idproyecto = request.form['idproyecto']
        proyecto = proyectoMgr.getProyecto(idproyecto)
        session['idproyecto'] = idproyecto 
        session['nombreProyecto']= proyecto.nombre
        session['liderProyecto']= proyecto.lider
        session['idfase'] = None
        session['nombreFase'] = None
        session['descripcionFase'] = None
        user = usuarioMgr.getUsuarioPorUser(session['username'])
        permisos = []
        roles = []
        nombreRol="Lider_"+session['nombreProyecto']
        rol2 = Rol()
        if session['username'] == "root":
                    for rol in user.roles:
                        roles.append(rol.nombre)
                        for permiso in rol.permisos:
                            if permiso not in permisos:
                                permisos.append(permiso.codigo)
        else:   
            if user.usuario == proyecto.lider.usuario:
                rol2 = rolMgr.getRolPorNombre(nombreRol)
            if rol2:
                for permiso in rol2.permisos:
                    permisos.append(permiso.codigo)
        session['permisos']= permisos
        if roles != []:
            roles.append(rol2.nombre)   
        session['roles'] = roles
        return redirect(url_for(action))

@app.route("/configurarFase", methods=["GET", "POST"])
def configurarFase():
    """Metodo encargado de consultar los datos de una fase de un proyecto"""
    if request.method == "GET":
        action = "configurarFase"
        if request.args.getlist('action'): 
            action = request.args.getlist('action')[0]
        if session['idproyecto']:
            idproyecto=session['idproyecto']
            proyecto=proyectoMgr.getProyecto(idproyecto)
            fases = faseMgr.getFasesPorProyecto(idproyecto)
            fase = None
            if session['idfase']:
                idfase = session['idfase']
                fase = faseMgr.getFase(idfase)
            return render_template("configFase.html", action = action, proyecto=proyecto, fase = fase, fases = fases)
        else:
            return redirect(url_for("configurarProyecto", action = action))

    if request.method == "POST":
        action = request.form['action']
        idproyecto=session['idproyecto']
        fases = faseMgr.getFasesPorProyecto(idproyecto)
        idfase = request.form['idfase']
        fase= faseMgr.getFase(idfase)
        session['idfase'] = idfase
        session['nombreFase'] = fase.nombre
        session['descripcionFase'] = fase.descripcion
        fase = faseMgr.getFase(idfase)
        user = usuarioMgr.getUsuarioPorUser(session['username'])
        permisos = []
        roles = []
        roles2 = []
        if session['username'] == "root":
                    for rol in user.roles:
                        roles2.append(rol.nombre)
                        for permiso in rol.permisos:
                            if permiso not in permisos:
                                permisos.append(permiso.codigo)
        else:

            for rol in user.roles:
                if rol.idfase == fase.idfase:
                    roles.append(rol)
            for rol in roles:
                roles2.append(rol.nombre)   
                for permiso in rol.permisos:
                    permisos.append(permiso.codigo)
        
        nombreRol="Lider_"+session['nombreProyecto']
        rol2 = Rol() 
        if user.usuario == fase.proyecto.lider.usuario:
            rol2 = rolMgr.getRolPorNombre(nombreRol)
        if rol2:
            for permiso in rol2.permisos:
                permisos.append(permiso.codigo) 
                    
        session['permisos']= permisos
        session['roles'] = roles2
        return redirect(url_for(action))

#         return render_template("configFase.html", fase = fase, fases = fases)

@app.route("/")
def index():
    """Metodo encargado del direccionamiento a la pagina principal"""
    session['idproyecto']=None
    session['idfase']=None
    session['idpermiso']=None
    session['nombreProyecto']= None
    session['liderProyecto']= None
    session['nombreFase'] = None
    session['descripcionFase'] = None
    session['permisos'] = []
    session['roles'] = []

    return render_template("index.html",name="verena")

@app.route("/menu")
def menu():
    """Metodo encargado del direccionamiento al menu principal"""
    
    return render_template("menuPrincipal.html")

@app.route("/login", methods=["GET", "POST"])
def login():
    """Metodo encargado de la autenticacion del usuario"""
    
    if request.method == "POST" and "user" in request.form:
        error = None
        username = request.form["user"]
        password = request.form["password"]
        # password = bz2.compress(password)
        user = usuarioMgr.getUsuarioPorUser(username)
        if(user):
            usuariobd = user.usuario
            contrasenha = user.contrasenha
            password = hashlib.sha1( password ).hexdigest()
            if username == usuariobd and contrasenha == password:
                session['username'] = username
                session['idproyecto']= None
                session['idfase']= None
                roles = []
                permisos = []
                if session['username'] == "admin":
                    for rol in user.roles:
                        roles.append(rol.nombre)
                        for permiso in rol.permisos:
                            if permiso not in permisos:
                                permisos.append(permiso.codigo)
                if session['username'] == "root":
                    for rol in user.roles:
                        roles.append(rol.nombre)
                        for permiso in rol.permisos:
                            if permiso not in permisos:
                                permisos.append(permiso.codigo)
                session['permisos'] = permisos
                session['roles'] = roles 
                return render_template("pantalla.html")
    
    session['idproyecto']=None
    session['idfase']=None
    session['idpermiso']=None
    session['nombreProyecto']= None
    session['liderProyecto']= None
    session['nombreFase'] = None
    session['descripcionFase'] = None
    session['permisos'] = []
    session['roles'] = []
    flash('Usuario o contrasenha invalidos')
    return render_template("index.html")

@app.route("/logout")
def logout():
    """Metodo encargado de la desautenticacion de un usuario"""
    session.pop('idpermiso', None)
    session.pop('liderProyecto', None)
    session.pop('nombreFase', None)

    session.pop('username', None)
    session.pop('idproyecto', None)
    session.pop('nombreProyecto', None)
    session.pop('idfase', None)
    session.pop('roles', None)
    session.pop('permisos', None)
    flash("Logged out.")
    return redirect(url_for("index"))

@app.route('/shutdown', methods=['GET', 'POST'])
def shutdown():
    shutdown_server()
    return 'Server shutting down...'

@app.route("/menuDesplegable")
def menuDesplegable():
    """Metodo encargado de cargar el menu proncipal del sistema"""
    
    return render_template("menuDesplegable.html")

@app.route("/top")
def top():
    """Metodo encargado de cargar el encabezado de la pagina principal"""
    
    return render_template("cabecera.html")

@app.route("/bienvenida")
def bienvenida():
    """Metodo encargado de cargar la pagina base"""
    
    return render_template("layout.html")
